/**
 * $version:  0.1 
 * $Date: 2011-01-21 
 *
 * Copyright (C) 2010-2011 Jawa Software. All rights reserved.
 *
 */
package org.jawa.admin;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;

import org.apache.commons.lang.StringUtils;
import org.jawa.menu.Menu;
import org.jawa.menu.MenuManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 * @author Y-N
 * 
 */
public class DisplayMenuTag extends TagSupport {

	private static final long serialVersionUID = -7856656315327706709L;
	private static final Logger Log = LoggerFactory.getLogger(DisplayMenuTag.class);

	// 菜单仓库在内存中的名称
	private String id;

	// 菜单仓库在内存中的名称
	private String repository;
	// 菜单的 target
	private String target;
	// 菜单的 css Class
	private String cssClass;

	protected JspWriter out;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public void setRepository(String repository) {
		this.repository = repository;
	}

	public String getRepository() {
		return repository;
	}

	public void setTarget(String target) {
		this.target = target;
	}

	public String getTarget() {
		return target;
	}

	public void setCssClass(String cssClass) {
		this.cssClass = cssClass;
	}

	public String getCssClass() {
		return cssClass;
	}

	/**
	 * 
	 * @return
	 */
	private MenuRepository findMenuRepository() {
		HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();

		Long pageID = (Long) request.getAttribute("pageID");
		if (null == pageID) {
			return null;
		}

		MenuManager menuManager = MenuManager.getInstance();

		List<Menu> userMenus = new ArrayList<Menu>(70);
		//没有考虑权限的问题
		userMenus = menuManager.getTopMenus();

		MenuRepository repository = new MenuRepository();
		for (Iterator<Menu> iterator = userMenus.iterator(); iterator.hasNext();) {
			Menu menu = (Menu) iterator.next();
			MenuComponent mc = new MenuComponent();
			mc.setMenuId(menu.getMenuId());
			mc.setMenuParentId(menu.getMenuParentId());
			Long menuParent = menu.getMenuParentId();
			if (menuParent != null) {
				MenuComponent parentMenu = repository.getMenu(menuParent);
				if (parentMenu == null) {
					parentMenu = new MenuComponent();
					parentMenu.setMenuId(menuParent);
					repository.addMenu(parentMenu);
				}
				mc.setParent(parentMenu);
			}
			mc.setMenuId(menu.getMenuId());
			mc.setMenuName(menu.getMenuName());
			if (StringUtils.isNotEmpty(menu.getMenuUrl())) {
				mc.setMenuUrl(request.getContextPath() + menu.getMenuUrl());
			}
			repository.addMenu(mc);
		}
		return repository;
	}

	/**
	 * 执行菜单标签
	 */
	public int doStartTag() throws JspException {

		HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
		MenuRepository repository = null;

		if (repository != null) {
			// 取出菜单仓库
			repository = (MenuRepository) pageContext.findAttribute(this.repository);
		} else {
			repository = findMenuRepository();
		}

		if (repository == null) {
			Log.info("没有找到可显示的菜单");

			return EVAL_PAGE;
		}

		out = pageContext.getOut();

		List topMenus = repository.getTopMenus();
		try {

			out.println("<ul id=\"" + StringUtils.trimToEmpty(id) + "\" class=\"" + StringUtils.trimToEmpty(cssClass)
					+ "\">");

			for (Iterator<MenuComponent> iterator = topMenus.iterator(); iterator.hasNext();) {
				MenuComponent topMenu = (MenuComponent) iterator.next();
				displayComponents(topMenu, 0);
			}

			out.println("</ul>");

		} catch (Exception e) {
			Log.error("显示菜单出错!", e);
		}
		return EVAL_PAGE;
	}

	/**
	 * 显示某一个菜单以及下级菜单组件。
	 * 
	 * @param menu
	 *            要显示的菜单组件
	 * @param level
	 *            要显示的菜单组件的级别
	 * @throws JspException
	 * @throws IOException
	 */
	protected void displayComponents(MenuComponent menu, int level) throws JspException, IOException {

		// 如果菜单没有定义URL
		if (null == menu.getMenuUrl()) {
			menu.setMenuUrl("javascript:void(0);");
		}

		// 取出当前菜单组件的下级菜单组件
		MenuComponent[] components = menu.getMenuComponents();

		// 如果下级中存在可以显示的菜单，即有权限显示
		if (hasViewableChildren(menu)) {

			out.println("<li>");

			out.print("<a  href=\"" + menu.getMenuUrl() + "\" ");

			if (null != target) {
				out.print(" target=\"" + target + "\" ");
			}
			out.println(" >" + menu.getMenuName() + "</a>");

			out.println("<ul>");

			for (int i = 0; i < components.length; i++) {
				// 判断当前下级菜单的权限，是否有权限显示
				if (isAllowed(components[i].getMenuId())) {

					// 如果仍然存在下级菜单
					if (hasViewableChildren(components[i])) {
						// 显示当前菜单以及下级菜单
						displayComponents(components[i], level + 1);

					} else {

						out.println("<li>");

						out.print("<a  href=\"" + components[i].getMenuUrl() + "\" ");

						if (null != target) {
							out.print(" target=\"" + target + "\" ");
						}
						out.println(" >" + components[i].getMenuName() + "</a>");

						out.println("</li>");
					}
				}
			}

			out.println("</ul>");

			out.println("</li>");

		} else {

			out.println("<li>");

			out.print("<a  href=\"" + menu.getMenuUrl() + "\" ");

			if (null != target) {
				out.print(" target=\"" + target + "\" ");
			}
			out.println(" >" + menu.getMenuName() + "</a>");

			out.println("</li>");
		}
	}

	/**
	 * 是否允许显示当前菜单,方便以后加入权限控制。
	 * 
	 * @param menuId
	 *            菜单编号
	 * @return
	 */
	public boolean isAllowed(Long menuId) {
		return true;
	}

	/**
	 * 当前菜单的下级菜单中是否有可能显示的。
	 * 
	 * @param menu
	 * @return
	 */
	private boolean hasViewableChildren(MenuComponent menu) {
		for (int i = 0; i < menu.getMenuComponents().length; i++) {
			if (isAllowed(menu.getMenuComponents()[i].getMenuId())) {
				return true;
			}
		}
		return false;
	}

	public void release() {
		this.repository = null;
		this.target = null;
	}

}
